<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数字网格可视化</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Arial', sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            height: 100vh;
            margin: 0;
            padding: 0;
            overflow-x: auto;
        }

        .container {
            width: 100vw;
            height: 100vh;
            background: white;
            padding: 20px;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }

        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
            font-size: 2em;
            background: linear-gradient(45deg, #667eea, #764ba2);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            flex-shrink: 0;
        }

        .controls {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 12px;
            margin-bottom: 15px;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 10px;
            flex-shrink: 0;
            max-height: 200px;
            overflow-y: auto;
        }

        .control-group {
            display: flex;
            flex-direction: column;
        }

        .control-group.full-width {
            grid-column: 1 / -1;
        }

        label {
            font-weight: bold;
            margin-bottom: 5px;
            color: #555;
        }

        input, select {
            padding: 10px;
            border: 2px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            transition: border-color 0.3s;
        }

        input:focus, select:focus {
            outline: none;
            border-color: #667eea;
        }

        #numbersInput {
            width: 100%;
            min-height: 50px;
            max-height: 80px;
            resize: vertical;
        }

        .button-group {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            flex-shrink: 0;
        }

        button {
            padding: 12px 24px;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
        }

        .btn-primary {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }

        .btn-secondary {
            background: #6c757d;
            color: white;
        }

        .btn-secondary:hover {
            background: #5a6268;
        }

        .grid-container {
            flex: 1;
            overflow: auto;
            padding: 0;
            min-height: 0;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            position: relative;
            /* 禁用滚动锚定，避免渲染后浏览器调整滚动位置 */
            overflow-anchor: none;
        }

        .grid {
            display: grid;
            gap: 1px;
            border: 2px solid #333;
            background: #f0f0f0;
            margin: 10px;
            /* 让网格按内容尺寸扩展，避免被容器裁剪 */
            width: max-content;
            height: max-content;
        }

        .cell {
            border: 1px solid #ccc;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            font-size: 12px;
            color: #333;
            background: white;
            transition: all 0.3s;
            position: relative;
        }

        .cell.filled {
            color: white;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
        }

        .cell:hover {
            transform: scale(1.1);
            z-index: 10;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
        }



        .color-preset {
            display: flex;
            gap: 10px;
            margin-top: 10px;
            flex-wrap: wrap;
        }

        .color-option {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            cursor: pointer;
            border: 3px solid transparent;
            transition: all 0.3s;
        }

        .color-option:hover {
            transform: scale(1.2);
            border-color: #333;
        }

        .color-option.selected {
            border-color: #333;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎨 数字网格可视化工具</h1>
        
        <div class="controls">
            <div class="control-group full-width">
                <label for="numbersInput">输入数字 (空格或逗号分隔):</label>
                <textarea id="numbersInput" placeholder="例如: 4 1 6 1 8 1 10 1 12 1 8 1 5 1 4 (循环模式，增量为4)"></textarea>
            </div>
            
            <div class="control-group">
                <label for="rows">行数:</label>
                <input type="number" id="rows" value="5" min="1" max="20">
            </div>
            
            <div class="control-group">
                <label for="cols">列数:</label>
                <input type="number" id="cols" value="5" min="1" max="20">
            </div>
            
            <div class="control-group">
                <label for="cellWidth">单元格宽度 (px):</label>
                <input type="number" id="cellWidth" value="40" min="20" max="100">
            </div>
            
            <div class="control-group">
                <label for="cellHeight">单元格高度 (px):</label>
                <input type="number" id="cellHeight" value="40" min="20" max="100">
            </div>
            
            <div class="control-group">
                <label for="fillColor">填充颜色:</label>
                <input type="color" id="fillColor" value="#667eea">
                <div class="color-preset">
                    <div class="color-option" style="background: #667eea" data-color="#667eea"></div>
                    <div class="color-option" style="background: #f093fb" data-color="#f093fb"></div>
                    <div class="color-option" style="background: #4facfe" data-color="#4facfe"></div>
                    <div class="color-option" style="background: #43e97b" data-color="#43e97b"></div>
                    <div class="color-option" style="background: #fa709a" data-color="#fa709a"></div>
                    <div class="color-option" style="background: #ffecd2" data-color="#ffecd2"></div>
                </div>
            </div>
            
            <div class="control-group">
                <label for="showNumbers">显示数字:</label>
                <select id="showNumbers">
                    <option value="true">显示</option>
                    <option value="false">隐藏</option>
                </select>
            </div>
            
            <div class="control-group">
                <label for="startPosition">开始位置:</label>
                <input type="number" id="startPosition" value="1" min="1" max="10000">
            </div>
        </div>
        
        <div class="button-group">
            <button class="btn-primary" onclick="generateGrid()">🎯 生成网格</button>
            <button class="btn-secondary" onclick="clearGrid()">🗑️ 清空网格</button>
            <button class="btn-secondary" onclick="loadExample()">📝 加载示例</button>
            <button class="btn-secondary" onclick="generateTestData()">🎲 随机测试数据</button>
        </div>
        
        <div class="grid-container">
            <div id="grid" class="grid"></div>
        </div>
        

    </div>

    <script>
        // 初始化颜色选择器
        document.querySelectorAll('.color-option').forEach(option => {
            option.addEventListener('click', function() {
                const color = this.dataset.color;
                document.getElementById('fillColor').value = color;
                
                // 更新选中状态
                document.querySelectorAll('.color-option').forEach(opt => opt.classList.remove('selected'));
                this.classList.add('selected');
                
                // 触发实时更新
                updateGridRealtime();
            });
        });

        // 设置默认选中的颜色
        document.querySelector('.color-option[data-color="#667eea"]').classList.add('selected');

        function parseNumbers(input) {
            // 支持空格和逗号分隔
            return input.trim()
                       .split(/[\s,]+/)
                       .filter(num => num !== '')
                       .map(num => parseInt(num))
                       .filter(num => !isNaN(num) && num >= 0);
        }

        function calculatePositions(numbers, totalCells, startOffset = 0) {
            const positions = [];
            
            if (numbers.length === 0) return positions;
            
            // 检查是否为奇数个数字（循环模式）
            if (numbers.length % 2 === 1) {
                // 循环模式：最后一个数字是增量
                const increment = numbers[numbers.length - 1];
                const pairs = numbers.slice(0, -1); // 去掉最后一个增量数字
                
                // 计算第一组的染色位置（累积偏移）
                const firstGroupPositions = [];
                let currentPos = 0;
                
                console.log('开始计算染色位置，输入:', pairs);
                
                for (let i = 0; i < pairs.length; i += 2) {
                    const offset = pairs[i];
                    const count = pairs[i + 1];
                    
                    // 累积位置：当前位置 + 偏移 + 1
                    currentPos = currentPos + offset + 1;
                    console.log(`第${i/2+1}组: offset=${offset}, count=${count}, currentPos=${currentPos}`);
                    
                    if (count === 0) {
                        // count为0时，染色当前位置
                        const adjustedPos = currentPos + startOffset;
                        firstGroupPositions.push(adjustedPos);
                        console.log(`  染色位置: ${adjustedPos} (原始: ${currentPos}, 偏移: ${startOffset})`);
                    } else {
                        // count>0时，从当前位置开始染色count个格子
                        for (let j = 0; j < count; j++) {
                            const adjustedPos = currentPos + j + startOffset;
                            firstGroupPositions.push(adjustedPos);
                            console.log(`  染色位置: ${adjustedPos} (原始: ${currentPos + j}, 偏移: ${startOffset})`);
                        }
                    }
                }
                
                console.log('第一组所有染色位置:', firstGroupPositions);
                
                // 将第一组位置添加到结果中
                positions.push(...firstGroupPositions);
                
                // 计算后续组，每组都从上一组的最后位置开始累积
                let lastGroupEndPos = Math.max(...firstGroupPositions);
                let groupCount = 1;
                
                while (true) {
                    console.log(`\n开始计算第${groupCount + 1}组，起始位置: ${lastGroupEndPos}`);
                    
                    let groupPositions = [];
                    let groupCurrentPos = lastGroupEndPos + increment; // 加上增量
                    let hasValidPosition = false;
                    
                    for (let i = 0; i < pairs.length; i += 2) {
                        const offset = pairs[i];
                        const count = pairs[i + 1];
                        
                        // 累积位置：当前位置 + 偏移 + 1
                        groupCurrentPos = groupCurrentPos + offset + 1;
                        console.log(`  第${i/2+1}块: offset=${offset}, count=${count}, groupCurrentPos=${groupCurrentPos}`);
                        
                        if (count === 0) {
                            const adjustedPos = groupCurrentPos + startOffset;
                            if (adjustedPos >= 1 && adjustedPos <= totalCells) {
                                groupPositions.push(adjustedPos);
                                positions.push(adjustedPos);
                                hasValidPosition = true;
                                console.log(`    染色位置: ${adjustedPos} (原始: ${groupCurrentPos}, 偏移: ${startOffset})`);
                            }
                        } else {
                            for (let j = 0; j < count; j++) {
                                const adjustedPos = groupCurrentPos + j + startOffset;
                                if (adjustedPos >= 1 && adjustedPos <= totalCells) {
                                    groupPositions.push(adjustedPos);
                                    positions.push(adjustedPos);
                                    hasValidPosition = true;
                                    console.log(`    染色位置: ${adjustedPos} (原始: ${groupCurrentPos + j}, 偏移: ${startOffset})`);
                                }
                            }
                        }
                    }
                    
                    // 如果这一组没有任何有效位置，退出循环
                    if (!hasValidPosition) {
                        console.log(`第${groupCount + 1}组没有有效位置，结束循环`);
                        break;
                    }
                    
                    // 更新最后位置为当前组的最后位置
                    if (groupPositions.length > 0) {
                        lastGroupEndPos = Math.max(...groupPositions);
                        console.log(`第${groupCount + 1}组结束位置: ${lastGroupEndPos}`);
                    }
                    
                    groupCount++;
                    
                    // 安全检查，避免无限循环
                    if (groupCount > Math.ceil(totalCells / increment) + 10) {
                        break;
                    }
                }
                
            } else {
                // 原有的配对模式
                for (let i = 0; i < numbers.length; i += 2) {
                    if (i + 1 < numbers.length) {
                        const startPos = numbers[i];
                        const count = numbers[i + 1];
                        
                        if (startPos >= 1) {
                            if (count === 0) {
                                positions.push(startPos);
                            } else if (count > 0) {
                                for (let j = 1; j <= count; j++) {
                                    positions.push(startPos + j);
                                }
                            }
                        }
                    }
                }
            }
            
            return positions;
        }

        function generateGrid() {
            const numbersInput = document.getElementById('numbersInput').value;
            const rows = parseInt(document.getElementById('rows').value) || 5;
            const cols = parseInt(document.getElementById('cols').value) || 5;
            const cellWidth = parseInt(document.getElementById('cellWidth').value) || 40;
            const cellHeight = parseInt(document.getElementById('cellHeight').value) || 40;
            const fillColor = document.getElementById('fillColor').value;
            const showNumbers = document.getElementById('showNumbers').value === 'true';
            const startPosition = parseInt(document.getElementById('startPosition').value) || 1;
            const startOffset = startPosition - 1; // 计算偏移量
            
            // 如果没有输入数字，显示空网格
            const inputNumbers = numbersInput.trim() ? parseNumbers(numbersInput) : [];
            const totalCells = rows * cols;
            const positions = inputNumbers.length > 0 ? calculatePositions(inputNumbers, totalCells, startOffset) : [];
            const positionSet = new Set(positions);
            
            const grid = document.getElementById('grid');
            const gridContainer = document.querySelector('.grid-container');
            // 先复位滚动，避免追加大量节点时浏览器保持锚点造成偏移
            if (gridContainer) {
                gridContainer.scrollTop = 0;
                gridContainer.scrollLeft = 0;
            }
            grid.innerHTML = '';
            
            // 设置网格样式
            grid.style.gridTemplateColumns = `repeat(${cols}, ${cellWidth}px)`;
            grid.style.gridTemplateRows = `repeat(${rows}, ${cellHeight}px)`;
            
            // 创建网格单元格（使用片段减少布局抖动）
            const frag = document.createDocumentFragment();
            for (let i = 0; i < totalCells; i++) {
                const cell = document.createElement('div');
                cell.className = 'cell';
                const r = Math.floor(i / cols) + 1;
                const c = (i % cols) + 1;
                cell.style.gridRow = r;
                cell.style.gridColumn = c;
                if (positionSet.has(i + 1)) {
                    cell.classList.add('filled');
                    cell.style.backgroundColor = fillColor;
                    if (showNumbers) cell.textContent = i + 1;
                } else {
                    if (showNumbers) cell.textContent = i + 1;
                }
                frag.appendChild(cell);
            }
            grid.appendChild(frag);
            

            
            // 强制滚动到左上角（多帧确保复位）
            setTimeout(scrollToTop, 0);
            requestAnimationFrame(scrollToTop);
            setTimeout(scrollToTop, 100);
        }

        function clearGrid() {
            document.getElementById('grid').innerHTML = '';
            document.getElementById('numbersInput').value = '';
        }

        // 实时预览功能
        function updateGridRealtime() {
            const grid = document.getElementById('grid');
            if (grid.children.length > 0) {
                generateGrid();
            }
        }

        // 颜色实时更新
        document.getElementById('fillColor').addEventListener('input', function() {
            const filledCells = document.querySelectorAll('.cell.filled');
            filledCells.forEach(cell => {
                cell.style.backgroundColor = this.value;
            });
        });

        // 所有参数实时更新
        document.getElementById('numbersInput').addEventListener('input', updateGridRealtime);
        document.getElementById('rows').addEventListener('input', updateGridRealtime);
        document.getElementById('cols').addEventListener('input', updateGridRealtime);
        document.getElementById('cellWidth').addEventListener('input', updateGridRealtime);
        document.getElementById('cellHeight').addEventListener('input', updateGridRealtime);
        document.getElementById('fillColor').addEventListener('input', updateGridRealtime);
        document.getElementById('showNumbers').addEventListener('change', updateGridRealtime);
        document.getElementById('startPosition').addEventListener('input', updateGridRealtime);

        // 添加示例数据按钮功能
        function loadExample() {
            document.getElementById('numbersInput').value = '4 1 6 1 8 1 10 1 12 1 8 1 5 1 4';
            document.getElementById('rows').value = '10';
            document.getElementById('cols').value = '20';
            // 实时更新会自动触发generateGrid()
        }

        // 生成测试数据
        function generateTestData() {
            const testCases = [
                // 循环模式测试
                '',  // 第3,5,7格染色，增量3，循环模式
                
                // 复杂循环模式
                '1.2.5.1.8.2.4',  // 第2-3,6,9-10格染色，增量4，循环模式
                
                // 包含0的循环模式
                '3.0.6.1.9.0.5',  // 第3,7,9格染色，增量5，循环模式
                
                // 大增量循环
                '1.1.3.1.5.1.10',  // 第2,4,6格染色，增量10，循环模式
                
                // 混合宽度循环
                '2.2.6.1.10.3.8',  // 第3-4,7,11-13格染色，增量8，循环模式
                
                // 传统配对模式（偶数个）
                '1.1.4.0.7.2',  // 第2格，第4格，第8-9格染色，配对模式
                
                // 密集循环模式
                '1.0.2.0.3.0.2',  // 第1,2,3格染色，增量2，循环模式
                
                // 复杂循环图案
                '5.1.8.2.12.1.15.0.6'  // 复杂循环图案，增量6
            ];
            
            const randomIndex = Math.floor(Math.random() * testCases.length);
            document.getElementById('numbersInput').value = testCases[randomIndex];
            
            // 根据数据调整网格大小
            if (randomIndex >= 4) {
                document.getElementById('rows').value = '5';
                document.getElementById('cols').value = '6';
            } else {
                document.getElementById('rows').value = '4';
                document.getElementById('cols').value = '5';
            }
        }

        // 键盘快捷键
        document.addEventListener('keydown', function(e) {
            if (e.ctrlKey && e.key === 'Enter') {
                generateGrid();
            }
        });

        // 页面加载时生成默认网格
        window.addEventListener('load', function() {
            generateGrid();
        });

        // 强制滚动到左上角
        function scrollToTop() {
            const gridContainer = document.querySelector('.grid-container');
            if (!gridContainer) return;
            gridContainer.scrollTop = 0;
            gridContainer.scrollLeft = 0;
            // 第二帧再复位一次，规避渲染完成后的锚定修正
            requestAnimationFrame(() => {
                gridContainer.scrollTop = 0;
                gridContainer.scrollLeft = 0;
            });
        }
    </script>
</body>
</html>
